#include "base_server.cpp"

void sig_child(int), sig_init(int), web_child(int);
pid_t child_make(int, int, socklen_t);
void child_main(int, int, socklen_t);
pid_t *pids;//pids数组哟
int poolSize = 10;

//预先创建进程池服务器(accept函数不加锁，会有惊群)
//因为accept不是原子操作，所以某些子进程的accept就会返回EPROTO错误
//部分linux系统已修复上述问题，部分还存在，所以需要考虑给accept加锁
int main(){

    int listenfd, connfd;
    pid_t childPid;
    int port = 9011;
    
    socklen_t clilen, addrlen;
    struct sockaddr *cliaddr; 

    listenfd = tcp_create_bind_listen(port);

    //创建进程池
    pids = (pid_t*)calloc(poolSize, sizeof(pid_t));
    for(int i = 0; i < poolSize; i++){
        pids[i] = child_make(i, listenfd, addrlen);
    }

    signal(SIGTERM, sig_init);
    signal(SIGINT, sig_init);
    signal(SIGKILL, sig_init);

    for(;;){
        pause();
    }

    printf("main process stop\n");

    return 0;
}

pid_t child_make(int index, int listenfd, socklen_t addrlen){
    pid_t childPid;
    childPid = fork();
    if(childPid > 0){
        //父进程
        return childPid;
    }

    child_main(index, listenfd, addrlen);
}

void child_main(int index, int listenfd, socklen_t addrlen){
    printf("child %d is starting, getpid()=%d\n", index, getpid());
    int connfd;
    socklen_t clilen;
    struct sockaddr *cliaddr;
    cliaddr = (sockaddr *)malloc(addrlen);
    for(;;){
        clilen = addrlen;
        connfd = accept(listenfd, cliaddr, &clilen);
        web_child(connfd);
        close(connfd);
    }
}

void sig_child(int signo){
    printf("sign handle SIGCHLD\n");
    wait(NULL);
}

//程序退出后kill掉所有子进程，防止他们成为孤儿进程(孤儿进程倒没什么，主要是这个demo里的子进程是死循环，所以会一直存在，监听的端口也没释放)
void sig_init(int signo){
    printf("sign handle SIGINT\n");
    for(int i = 0; i < poolSize; i++){
        kill(pids[i], SIGTERM);
    }
    wait(NULL);
    exit(0);
}

void web_child(int connfd){
    printf("recv client connfd=%d\n", connfd);
    //sleep(3);
    
    char sendBuff[1025] = "你好呀，连接成功";
    write(connfd, sendBuff, strlen(sendBuff));

    // char buffer[256];
    // int n=0;
    // bzero(buffer, 256);
    // n = read(connfd, buffer, 255);
    // if(n < 0){
    //     error_func("read socket失败", n);
    // }
    // printf("web handle read(fd, buffer, num):%s\n", buffer);

}

